using System;
using System.Reflection;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.ResponseCompression;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using Serilog;
using UwinEducation.API.Middleware;
using UwinEducation.Application;
using UwinEducation.Application.Common.Interfaces;
using UwinEducation.Application.Extensions;
using UwinEducation.Infrastructure.Persistence;
using Microsoft.AspNetCore.Mvc;
using UwinEducation.Shared.Models;
using Microsoft.VisualBasic.FileIO;
using System.IO.Compression;
using Microsoft.AspNetCore.Server.Kestrel.Core;

namespace UwinEducation.API
{
    public class Program
    {
        public static async Task Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);

            builder.WebHost.UseIIS().UseIISIntegration();

            // 配置Kestrel服务器，允许同步IO操作
            builder.Services.Configure<KestrelServerOptions>(options =>
            {
                options.AllowSynchronousIO = true;
            });

            // 配置IIS服务器，允许同步IO操作
            builder.Services.Configure<IISServerOptions>(options =>
            {
                options.AllowSynchronousIO = true;
            });

            // 添加响应压缩服务
            builder.Services.AddResponseCompression(options =>
            {
                options.EnableForHttps = true; // 启用HTTPS的压缩
                options.Providers.Add<GzipCompressionProvider>();
                // 设置压缩的MIME类型
                options.MimeTypes = new[]
                {
                    "application/json",
                    "application/xml",
                    "text/plain",
                    "text/json",
                    "text/xml",
                    "application/javascript",
                    "text/css",
                    "text/html"
                };
            });

            // 配置GZIP压缩选项
            builder.Services.Configure<GzipCompressionProviderOptions>(options =>
            {
                // 设置压缩级别为最佳压缩
                options.Level = CompressionLevel.Optimal;
            });

            // Add services to the container.
            builder.Services.AddControllers();
            // 添加跨域配置
            builder.Services.AddCors(options =>
            {
                options.AddPolicy("AllowAllOrigins", policy =>
                {
                    policy.AllowAnyHeader()
                          .AllowAnyOrigin()
                          .AllowAnyMethod();

                    //.AllowCredentials();
                });
            });
            builder.Services.AddEndpointsApiExplorer();
            builder.Services.AddSwaggerGen(options =>
            {
                options.SwaggerDoc("v1", new OpenApiInfo { Title = "UwinEducation API", Version = "v1" });
                
                // 添加所有相关程序集的 XML 文档
                var xmlFiles = new[] {
                    $"{AppDomain.CurrentDomain.FriendlyName}.xml",                    // API 项目的 XML
                    "UwinEducation.Shared.xml",                                       // Shared 项目的 XML
                    "UwinEducation.Application.xml"                                   // Application 项目的 XML
                };

                foreach (var xmlFile in xmlFiles)
                {
                    var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                    if (File.Exists(xmlPath))
                    {
                        options.IncludeXmlComments(xmlPath, true);
                    }
                }

                // 对action的名称进行排序
                options.OrderActionsBy(o => o.RelativePath);

                // 添加JWT认证配置
                options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
                {
                    Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
                    Name = "Authorization",
                    In = ParameterLocation.Header,
                    Type = SecuritySchemeType.ApiKey,
                    Scheme = "Bearer"
                });

                options.AddSecurityRequirement(new OpenApiSecurityRequirement
                {
                    {
                        new OpenApiSecurityScheme
                        {
                            Reference = new OpenApiReference
                            {
                                Type = ReferenceType.SecurityScheme,
                                Id = "Bearer"
                            }
                        },
                        Array.Empty<string>()
                    }
                });
            });


            // 添加 HTTP 上下文访问器
            builder.Services.AddHttpContextAccessor();

            // 配置数据库
            builder.Services.AddDbContext<ApplicationDbContext>(options =>
            {
                string connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
                var serverVersion = ServerVersion.AutoDetect(connectionString);
                options.UseMySql(connectionString, serverVersion);
            });

            builder.Services.AddAutoMapperExt();
            // 添加应用层服务
            builder.Services.AddApplicationLayer(builder.Configuration);
           

            // 配置 JWT 认证
            builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(options =>
                {
                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuer = true,
                        ValidateAudience = true,
                        ValidateLifetime = true,
                        ValidateIssuerSigningKey = true,
                        ValidIssuer = builder.Configuration["Jwt:Issuer"],
                        ValidAudience = builder.Configuration["Jwt:Audience"],
                        IssuerSigningKey = new SymmetricSecurityKey(
                            Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))
                    };
                    //options.Events = new JwtBearerEvents
                    //{
                    //    OnTokenValidated = async context =>
                    //    {
                    //        try
                    //        {
                    //            var userId = context.Principal.FindFirst(ClaimTypes.NameIdentifier)?.Value;
                    //            if (string.IsNullOrEmpty(userId))
                    //            {
                    //                context.Fail("Invalid token");
                    //                return;
                    //            }

                    //            var cacheService = context.HttpContext.RequestServices
                    //                .GetRequiredService<ICacheService>();

                    //            var currentToken = context.HttpContext.Request.Headers["Authorization"]
                    //                .ToString().Replace("Bearer ", "");

                    //            // 检查是否是当前有效的token
                    //            var validToken = await cacheService.GetAsync<string>($"valid_token:{userId}");
                    //            if (validToken != currentToken)
                    //            {
                    //                context.Fail("Token is no longer valid");
                    //                return;
                    //            }
                    //        }
                    //        catch
                    //        {
                    //            context.Fail("Token validation failed");
                    //        }
                    //    }
                    //};
                });

            // 配置Redis缓存
            builder.Services.AddStackExchangeRedisCache(options =>
            {
                options.Configuration = builder.Configuration.GetConnectionString("Redis");
            });



            // 配置 Serilog
            builder.Host.UseSerilog((context, configuration) =>
            {
                configuration
                    .ReadFrom.Configuration(context.Configuration)
                    .Enrich.FromLogContext()
                    .WriteTo.Console()
                    .WriteTo.File(
                        path: "Logs/log-.txt",
                        rollingInterval: RollingInterval.Day,
                        rollOnFileSizeLimit: true,
                        retainedFileCountLimit: 31);
            });

            builder.Services.Configure<ApiBehaviorOptions>(options =>
            {
                options.InvalidModelStateResponseFactory = actionContext =>
                {
                    var errors = actionContext.ModelState
                        .Where(e => e.Value.Errors.Count > 0)
                        .SelectMany(x => x.Value.Errors)
                        .Select(x => x.ErrorMessage)
                        .ToList();

                    var errorMessage = string.Join(", ", errors);
                    
                    return new BadRequestObjectResult(ApiResponse<object>.Error(
                        errorMessage,
                        400
                    ));
                };
            });

            var app = builder.Build();
            // 在其他中间件之前使用跨域
            app.UseCors("AllowAllOrigins");

            // 使用自定义响应压缩中间件（只压缩大于50KB的响应）
            app.UseResponseCompression50KB();

            // Configure the HTTP request pipeline.
            if (app.Environment.IsDevelopment())
            {
                app.UseSwagger();
                app.UseSwaggerUI(c =>
                {
                    c.SwaggerEndpoint("/swagger/v1/swagger.json", "UwinEducation API V1");
                });
            }

            var enableInitialization = app.Configuration.GetValue<bool>("DatabaseInitialization:Enable");
            //TODO 为了方便调试，暂时关闭数据库初始化
            //enableInitialization = true;
            //if (enableInitialization)
            //{
            //    // 初始化数据库
            //    using (var scope = app.Services.CreateScope())
            //    {
            //        var initializer = scope.ServiceProvider.GetRequiredService<DbInitializer>();
            //        await initializer.InitializeAsync();
            //    }
            //}
            // 在其他中间件之前添加请求响应日志中间件
            app.UseMiddleware<RequestResponseLoggingMiddleware>();

            // 在其他中间件之前添加全局异常处理中间件
            app.UseMiddleware<GlobalExceptionMiddleware>();



            app.UseHttpsRedirection();

            //app.UseRouting();
            // 确保认证和授权中间件在权限中间件之前
            app.UseAuthentication();
            app.UseAuthorization();

            // 使用权限中间件
            app.UseMiddleware<PermissionAuthorizationMiddleware>();

            app.MapControllers();

            // 获取配置中的版本号
            var version = app.Configuration["AppVersion"] ?? "Unknown Version";

            // 设置ApiResponse的静态版本号
            UwinEducation.Shared.Models.ApiResponse<object>.AppVersion = version;

            // 在应用启动时打印版本日志
            app.Lifetime.ApplicationStarted.Register(() =>
            {
                var logger = app.Services.GetRequiredService<ILogger<Program>>();
                logger.LogInformation("API 启动，当前版本: {Version}", version);
                
                // 初始化服务定位器
                UwinEducation.Application.Common.Helpers.ServiceLocator.Initialize(app.Services);
                
                // 预热数据库连接
                // logger.LogInformation("正在预热数据库连接...");
                // try
                // {
                //     using (var scope = app.Services.CreateScope())
                //     {
                //         // 获取DbContext
                //         var dbContext = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
                        
                //         // 打开数据库连接
                //         dbContext.Database.OpenConnection();
                        
                //         // 执行一个简单查询以触发EF Core模型构建
                //         dbContext.Users.AsNoTracking().Take(1).ToList();
                        
                //         // 预热常用查询
                //         dbContext.SystemConfigs.AsNoTracking().Take(10).ToList();
                //         dbContext.Roles.AsNoTracking().Take(10).ToList();
                //         dbContext.Permissions.AsNoTracking().Take(10).ToList();
                        
                //         logger.LogInformation("数据库连接预热完成");
                //     }
                // }
                // catch (Exception ex)
                // {
                //     logger.LogError(ex, "数据库连接预热失败");
                // }
            });

            await app.RunAsync();
        }
    }
}